package mysql

import (
	"data-transfer/domain"
	"data-transfer/global"
	"data-transfer/transfer"
	"encoding/json"
	"fmt"
	"github.com/shopspring/decimal"
	"go.uber.org/zap"
	"strconv"
	"strings"
)
import "context"

//GetTqSkImportEventBySymbolAndCompCode 根据symbol和compCode取得大事提醒
func (mdb *db) GetTqSkImportEventBySymbolAndCompCode(ctx context.Context, symbol string, compCode string) ([]*domain.TQ_SK_IMPORTEVENT, error) {
	var results []*domain.TQ_SK_IMPORTEVENT
	err := mdb.db.NewSession().Where("ISVALID = ? and SYMBOL = ? and COMPCODE = ?", 1, symbol, compCode).Find(&results)
	return results, err

}

// GetTqSkBonusByCompCode 根据compCode取得股票分红
func (mdb *db) GetTqSkBonusByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_BONUS, error) {
	var results []*domain.TQ_SK_BONUS
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetAllEventRemind 根据股票信息 获取所有公司大事信息
func (mdb *db) GetAllEventRemind(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.EVENT_REMIND, error) {

	var rows []*domain.EVENT_REMIND

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange
		importEvents, err := mdb.GetTqSkImportEventBySymbolAndCompCode(ctx, symbol, compCode)

		if err != nil {
			global.LOG.Error("获取 公司大事数据出错:", zap.Any("err", err))
			return nil, err
		}

		for _, e := range importEvents {
			r := new(domain.EVENT_REMIND)
			r.Declaredate = e.Declaredate //公告日期
			r.Eventtext = e.Eventtext     //内容简介
			r.Symbol = e.Symbol
			r.Compcode = e.Compcode
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Sourcetable = e.Sourcetable                   //栏目标识
			r.Eventtitle = e.Eventtitle                     //标题
			r.Rank = e.Rank                                 //排序

			rows = append(rows, r)
		}

	}

	return rows, nil
}

//GetAllDividend 取得所有分红配送
func (mdb *db) GetAllDividend(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.DIVIDEND, error) {
	var rows []*domain.DIVIDEND

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		bonus, err := mdb.GetTqSkBonusByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取 股票分红出错:", zap.Any("err", err))
			return nil, err
		}

		for _, b := range bonus {
			r := new(domain.DIVIDEND)
			r.Compcode = b.Compcode
			r.Symbol = symbol
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Bonusimpdate = b.Bonusimpdate                 //分红实施公告日
			r.Cdividend = b.Cdividend                       //'税前红利（报价币种)
			r.Exrightdate = b.Exrightdate                   //除权除息日
			r.Bonusyear = b.Bonusyear                       //分红实施年度
			r.Dividtype = b.Dividtype                       //权益日期类型
			r.Divitype = b.Divitype                         //权益类型

			rows = append(rows, r)
		}

	}
	return rows, nil
}

// GetAllMargin 取得所有融资融券
func (mdb *db) GetAllMargin(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.MARGIN, error) {
	var rows []*domain.MARGIN

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		mrgInifos, err := mdb.GetTqSkFinMrgnInfoBySymbol(ctx, symbol)
		if err != nil {
			global.LOG.Error("获取 融资融券出错:", zap.Any("err", err))
			return nil, err
		}

		for _, m := range mrgInifos {
			r := new(domain.MARGIN)

			r.Symbol = symbol
			r.Compcode = compCode
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Finbalance = m.Finbalance                     //融资余额'
			r.Finbuyamt = m.Finbuyamt                       ///融资买入额
			r.Tradedate = m.Tradedate                       //交易日期
			r.Mrggbal = m.Mrggbal                           //融券余量金额
			r.Mrgnresqty = m.Mrgnresqty                     //融券余量
			r.Mrgnsellamt = m.Mrgnsellamt                   //融券卖出量
			r.Finmrghbal = m.Finmrghbal                     //融资融券余额

			rows = append(rows, r)
		}
	}

	return rows, nil
}

// GetTqSkFinMrgnInfoBySymbol 根据Symbol获取融资融券交易明细
func (mdb *db) GetTqSkFinMrgnInfoBySymbol(ctx context.Context, symbol string) ([]*domain.TQ_SK_FINMRGNINFO, error) {
	var results []*domain.TQ_SK_FINMRGNINFO
	err := mdb.db.NewSession().Where("ISVALID = ? and SYMBOL = ?", 1, symbol).Find(&results)
	return results, err
}

// GetAllProfitForecastNew 取得所有业绩盈利预测, 从TQ_EXPT_SKSTATN表取值
func (mdb *db) GetAllProfitForecastNew(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.PROFIT_FORECAST, error) {
	var rows []*domain.PROFIT_FORECAST

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		skstatns, err := mdb.GetTqExptSkstatnBySymbol(ctx, symbol)
		if err != nil {
			global.LOG.Error("获取 个股一致预期失败:", zap.Any("err", err))
			return nil, err
		}

		for _, s := range skstatns {

			exc := transfer.TransferExchane(exchange) //市场代码

			//一致预测一期
			r1 := new(domain.PROFIT_FORECAST)

			r1.Symbol = symbol
			r1.Compcode = compCode
			r1.Exchange = exc //市场代码

			tendDate := ""
			if len(s.Tenddate) >= 4 {
				tendDate = s.Tenddate[:4]
			}

			if len(tendDate) > 0 {
				r1.Exptyear = tendDate           //年度
				r1.Publishdate = s.Publishdate   //研报日期
				r1.Opermincome = s.Tmbizincome   //一致预期营业收入（一期）
				r1.Retamaxprofits = s.Tnetprofit //一致预期净利润（一期）
				r1.Epsmaxfore = s.Teps           //一致预期每股收益(一期）

				rows = append(rows, r1)
			}

			//一致预测二期
			r2 := new(domain.PROFIT_FORECAST)

			r2.Symbol = symbol
			r2.Compcode = compCode
			r2.Exchange = exc //市场代码

			nendDate := ""
			if len(s.Nenddate) >= 4 {
				nendDate = s.Nenddate[:4]
			}
			if len(nendDate) > 0 {
				r2.Exptyear = nendDate           //年度
				r2.Publishdate = s.Publishdate   //研报日期
				r2.Opermincome = s.Nmbizincome   //一致预期营业收入（二期）
				r2.Retamaxprofits = s.Nnetprofit //一致预期净利润（二期）
				r2.Epsmaxfore = s.Neps           //一致预期每股收益（二期）

				rows = append(rows, r2)
			}

			//一致预测三期
			r3 := new(domain.PROFIT_FORECAST)

			r3.Symbol = symbol
			r3.Compcode = compCode
			r3.Exchange = exc //市场代码

			yanendDate := ""
			if len(s.Yanenddate) >= 4 {
				yanendDate = s.Yanenddate[:4]
			}

			if len(yanendDate) > 0 {
				r3.Exptyear = yanendDate           //年度
				r3.Publishdate = s.Publishdate     //研报日期
				r3.Opermincome = s.Yanmbizincome   //一致预期营业收入(三期)
				r3.Retamaxprofits = s.Yannetprofit //一致预期净利润（三期）
				r3.Epsmaxfore = s.Yaneps           //一致预期每股收益（三期）

				rows = append(rows, r3)
			}

		}
	}

	return rows, nil
}

// GetTqExptSkstatnBySymbol 根据symbol获取最新发布日期的个股一致预期信息
func (mdb *db) GetTqExptSkstatnBySymbol(ctx context.Context, symbol string) ([]*domain.TQ_EXPT_SKSTATN, error) {
	var results []*domain.TQ_EXPT_SKSTATN
	err := mdb.db.NewSession().Where("SYMBOL = ?", symbol).Desc("PUBLISHDATE").Limit(1).Find(&results)
	return results, err
}

// GetAllProfitForecast 取得所有公司盈利预测数据
func (mdb *db) GetAllProfitForecast(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.PROFIT_FORECAST, error) {
	var rows []*domain.PROFIT_FORECAST

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		performances, err := mdb.GetTqSkExptPerformanceByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取 公司盈利预测数据出错:", zap.Any("err", err))
			return nil, err
		}

		for _, p := range performances {
			r := new(domain.PROFIT_FORECAST)

			//只插入有效数据记录
			if (p.Epsmaxfore == "" || p.Epsmaxfore == "0.000000") &&
				(p.Retamaxprofits == "" || p.Retamaxprofits == "0.000000") &&
				(p.Opermincome == "" || p.Opermincome == "0.000000") {
				//三个值都为无效数据时，不插入数据
				continue
			} else {
				r.Symbol = symbol
				r.Compcode = compCode
				r.Exchange = transfer.TransferExchane(exchange) //市场代码
				r.Epsmaxfore = p.Epsmaxfore                     //每股收益(上限)
				r.Exptyear = p.Exptyear                         //年度
				r.Opermincome = p.Opermincome                   //主营业务收入预测
				r.Retamaxprofits = p.Retamaxprofits             //净利润预测(上限)
				r.Publishdate = p.Publishdate                   //信息发布日期
				r.Datasource = p.Datasource                     //预测信息来源
				r.Sessionbegdate = p.Sessionbegdate             //预测期起始日
				r.Sessionenddate = p.Sessionenddate             //预测期截止日
				r.Basessionbegdate = p.Basessionbegdate         //预测基期起始日
				r.Basessionenddate = p.Basessionenddate         //预测基期截止日

				rows = append(rows, r)
			}

		}
	}
	return rows, nil
}

// GetTqSkExptPerformanceByCompCode 根据CompCode取得上市公司业绩预测
func (mdb *db) GetTqSkExptPerformanceByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_EXPTPERFORMANCE, error) {
	var results []*domain.TQ_SK_EXPTPERFORMANCE
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

// GetStdRatingCounts 返回相应证券的标准评级的评级机构个数，
// stdRating枚举值为： 1:BUY 2:ENLARGE  3:NEUTRAL 4:REDUCE 5:SELL
func (mdb *db) GetStdRatingCounts(ctx context.Context, symbol string, stdRating string, ratingValid string) (int, error) {

	var count int

	counts, err := mdb.db.Query("SELECT COUNT(DISTINCT COMPNAME) CNT  FROM TQ_EXPT_SKINVRATING WHERE ISVALID=? and SYMBOL= ? and STDRATING= ?  AND RATINGVALID = ? GROUP BY STDRATING", "1", symbol, stdRating, ratingValid)
	if err != nil {
		global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", stdRating), zap.String("RatingValid", ratingValid), zap.Any("err", err))
		return 0, err
	}

	for _, v := range counts {
		count, err = strconv.Atoi(fmt.Sprintf("%s", v["CNT"]))
		if err != nil {
			count = 0
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错", zap.Any("err", err))

		}
	}

	return count, nil
}

//GetAllRatingCount 取得所有证券的评级机构统计个数
func (mdb *db) GetAllRatingCount(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.RATING_COUNT, error) {
	var rows []*domain.RATING_COUNT

	for _, v := range basicInfos {

		symbol := v.Symbol // 根据symbol来进行统计
		compCode := v.Compcode
		exchange := v.Exchange
		//评级有效期 1（3个月）,2（6个月）,3(12个月)，4(18个月)，0(无具体期限)
		//标准评级:1(买入)，2(增持)，3(中性)，4(减持)，5(卖出)

		//1.评级有效期为三个月的
		r3 := new(domain.RATING_COUNT)
		r3.Symbol = symbol                               //证券代码
		r3.Compcode = compCode                           //机构代码
		r3.Exchange = transfer.TransferExchane(exchange) //市场代码

		r3.Ratingvalid = transfer.RATINGVALID_3MONTH //评级有效期三个月

		//买入数量
		buy3Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_BUY, transfer.RATINGVALID_3MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_BUY), zap.String("RatingValid", transfer.RATINGVALID_3MONTH), zap.Any("err", err))
			buy3Cnt = 0 //出错设置为0
		}
		r3.Buy = buy3Cnt                      //买入数量
		r3.Stdrating = transfer.STDRATING_BUY //买入

		//增持数量
		enlarge3Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_ENLARGE, transfer.RATINGVALID_3MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_ENLARGE), zap.String("RatingValid", transfer.RATINGVALID_3MONTH), zap.Any("err", err))
			enlarge3Cnt = 0 //出错设置为0
		}
		r3.Enlarge = enlarge3Cnt                                       //增持数量
		r3.Stdrating = r3.Stdrating + "," + transfer.STDRATING_ENLARGE //增持

		//中性数量
		neutral3Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_NEUTRAL, transfer.RATINGVALID_3MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_NEUTRAL), zap.String("RatingValid", transfer.RATINGVALID_3MONTH), zap.Any("err", err))
			neutral3Cnt = 0 //出错设置为0
		}
		r3.Neutral = neutral3Cnt                                       //中性数量
		r3.Stdrating = r3.Stdrating + "," + transfer.STDRATING_NEUTRAL // 中性

		//减持数量
		reduce3Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_REDUCE, transfer.RATINGVALID_3MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_REDUCE), zap.String("RatingValid", transfer.RATINGVALID_3MONTH), zap.Any("err", err))
			reduce3Cnt = 0 //出错设置为0
		}
		r3.Reduce = reduce3Cnt                                        //减持数量
		r3.Stdrating = r3.Stdrating + "," + transfer.STDRATING_REDUCE //减持

		//卖出数量
		sell3Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_SELL, transfer.RATINGVALID_3MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_SELL), zap.String("RatingValid", transfer.RATINGVALID_3MONTH), zap.Any("err", err))
			sell3Cnt = 0 //出错设置为0
		}
		r3.Sell = sell3Cnt                                          //卖出数量
		r3.Stdrating = r3.Stdrating + "," + transfer.STDRATING_SELL //卖出

		// 增加评级有效期3个月的记录
		rows = append(rows, r3)

		//2.评级有效期为六个月的
		r6 := new(domain.RATING_COUNT)
		r6.Symbol = symbol                               //证券代码
		r6.Compcode = compCode                           //机构代码
		r6.Exchange = transfer.TransferExchane(exchange) //市场代码

		r6.Ratingvalid = transfer.RATINGVALID_6MONTH //评级有效期六个月

		//买入数量
		buy6Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_BUY, transfer.RATINGVALID_6MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_BUY), zap.String("RatingValid", transfer.RATINGVALID_6MONTH), zap.Any("err", err))

			buy6Cnt = 0 //出错设置为0
		}
		r6.Buy = buy6Cnt                      //买入数量
		r6.Stdrating = transfer.STDRATING_BUY //买入

		//增持数量
		enlarge6Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_ENLARGE, transfer.RATINGVALID_6MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_ENLARGE), zap.String("RatingValid", transfer.RATINGVALID_6MONTH), zap.Any("err", err))

			enlarge6Cnt = 0 //出错设置为0
		}
		r6.Enlarge = enlarge6Cnt                                       //增持数量
		r6.Stdrating = r6.Stdrating + "," + transfer.STDRATING_ENLARGE //增持

		//中性数量
		neutral6Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_NEUTRAL, transfer.RATINGVALID_6MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_NEUTRAL), zap.String("RatingValid", transfer.RATINGVALID_6MONTH), zap.Any("err", err))

			neutral6Cnt = 0 //出错设置为0
		}
		r6.Neutral = neutral6Cnt                                       //中性数量
		r6.Stdrating = r6.Stdrating + "," + transfer.STDRATING_NEUTRAL // 中性

		//减持数量
		reduce6Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_REDUCE, transfer.RATINGVALID_6MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_REDUCE), zap.String("RatingValid", transfer.RATINGVALID_6MONTH), zap.Any("err", err))

			reduce6Cnt = 0 //出错设置为0
		}
		r6.Reduce = reduce6Cnt                                        //减持数量
		r6.Stdrating = r6.Stdrating + "," + transfer.STDRATING_REDUCE //减持

		//卖出数量
		sell6Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_SELL, transfer.RATINGVALID_6MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_SELL), zap.String("RatingValid", transfer.RATINGVALID_6MONTH), zap.Any("err", err))

			sell6Cnt = 0 //出错设置为0
		}
		r6.Sell = sell6Cnt                                          //卖出数量
		r6.Stdrating = r6.Stdrating + "," + transfer.STDRATING_SELL //卖出

		// 增加评级有效期6个月的记录
		rows = append(rows, r6)

		//3.评级有效期为十二个月的
		r12 := new(domain.RATING_COUNT)
		r12.Symbol = symbol                               //证券代码
		r12.Compcode = compCode                           //机构代码
		r12.Exchange = transfer.TransferExchane(exchange) //市场代码

		r12.Ratingvalid = transfer.RATINGVALID_12MONTH //评级有效期十二个月

		//买入数量
		buy12Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_BUY, transfer.RATINGVALID_12MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_BUY), zap.String("RatingValid", transfer.RATINGVALID_12MONTH), zap.Any("err", err))

			buy12Cnt = 0 //出错设置为0
		}
		r12.Buy = buy12Cnt                     //买入数量
		r12.Stdrating = transfer.STDRATING_BUY //买入

		//增持数量
		enlarge12Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_ENLARGE, transfer.RATINGVALID_12MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_ENLARGE), zap.String("RatingValid", transfer.RATINGVALID_12MONTH), zap.Any("err", err))

			enlarge12Cnt = 0 //出错设置为0
		}
		r12.Enlarge = enlarge12Cnt                                       //增持数量
		r12.Stdrating = r12.Stdrating + "," + transfer.STDRATING_ENLARGE //增持

		//中性数量
		neutral12Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_NEUTRAL, transfer.RATINGVALID_12MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_NEUTRAL), zap.String("RatingValid", transfer.RATINGVALID_12MONTH), zap.Any("err", err))

			neutral12Cnt = 0 //出错设置为0
		}
		r12.Neutral = neutral12Cnt                                       //中性数量
		r12.Stdrating = r12.Stdrating + "," + transfer.STDRATING_NEUTRAL // 中性

		//减持数量
		reduce12Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_REDUCE, transfer.RATINGVALID_12MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_REDUCE), zap.String("RatingValid", transfer.RATINGVALID_12MONTH), zap.Any("err", err))

			reduce12Cnt = 0 //出错设置为0
		}
		r12.Reduce = reduce12Cnt                                        //减持数量
		r12.Stdrating = r12.Stdrating + "," + transfer.STDRATING_REDUCE //减持

		//卖出数量
		sell12Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_SELL, transfer.RATINGVALID_12MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_SELL), zap.String("RatingValid", transfer.RATINGVALID_12MONTH), zap.Any("err", err))

			sell12Cnt = 0 //出错设置为0
		}
		r12.Sell = sell12Cnt                                          //卖出数量
		r12.Stdrating = r12.Stdrating + "," + transfer.STDRATING_SELL //卖出

		// 增加评级有效期12个月的记录
		rows = append(rows, r12)

		//4.评级有效期为十八个月的
		r18 := new(domain.RATING_COUNT)
		r18.Symbol = symbol                               //证券代码
		r18.Compcode = compCode                           //机构代码
		r18.Exchange = transfer.TransferExchane(exchange) //市场代码

		r18.Ratingvalid = transfer.RATINGVALID_18MONTH //评级有效期十八个月

		//买入数量
		buy18Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_BUY, transfer.RATINGVALID_18MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_BUY), zap.String("RatingValid", transfer.RATINGVALID_18MONTH), zap.Any("err", err))

			buy18Cnt = 0 //出错设置为0
		}
		r18.Buy = buy18Cnt                     //买入数量
		r18.Stdrating = transfer.STDRATING_BUY //买入

		//增持数量
		enlarge18Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_ENLARGE, transfer.RATINGVALID_18MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_ENLARGE), zap.String("RatingValid", transfer.RATINGVALID_18MONTH), zap.Any("err", err))

			enlarge18Cnt = 0 //出错设置为0
		}
		r18.Enlarge = enlarge18Cnt                                       //增持数量
		r18.Stdrating = r18.Stdrating + "," + transfer.STDRATING_ENLARGE //增持

		//中性数量
		neutral18Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_NEUTRAL, transfer.RATINGVALID_18MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_NEUTRAL), zap.String("RatingValid", transfer.RATINGVALID_18MONTH), zap.Any("err", err))

			neutral18Cnt = 0 //出错设置为0
		}
		r18.Neutral = neutral18Cnt                                       //中性数量
		r18.Stdrating = r18.Stdrating + "," + transfer.STDRATING_NEUTRAL // 中性

		//减持数量
		reduce18Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_REDUCE, transfer.RATINGVALID_18MONTH)
		if err != nil {
			global.LOG.Error("获取标准评级和评级有效期的机构个数出错:%v:", zap.String("StdRating", transfer.STDRATING_REDUCE), zap.String("RatingValid", transfer.RATINGVALID_18MONTH), zap.Any("err", err))

			reduce18Cnt = 0 //出错设置为0
		}
		r18.Reduce = reduce18Cnt                                        //减持数量
		r18.Stdrating = r18.Stdrating + "," + transfer.STDRATING_REDUCE //减持

		//卖出数量
		sell18Cnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_SELL, transfer.RATINGVALID_18MONTH)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_SELL), zap.String("RatingValid", transfer.RATINGVALID_18MONTH), zap.Any("err", err))

			sell18Cnt = 0 //出错设置为0
		}
		r18.Sell = sell18Cnt                                          //卖出数量
		r18.Stdrating = r18.Stdrating + "," + transfer.STDRATING_SELL //卖出

		// 增加评级有效期18个月的记录
		rows = append(rows, r18)

		//5.评级有效期为无具体期限的
		rNO := new(domain.RATING_COUNT)
		rNO.Symbol = symbol                               //证券代码
		rNO.Compcode = compCode                           //机构代码
		rNO.Exchange = transfer.TransferExchane(exchange) //市场代码

		rNO.Ratingvalid = transfer.RATINGVALID_NO //评级有效期无具体期限的

		//买入数量
		buyNOCnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_BUY, transfer.RATINGVALID_NO)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_BUY), zap.String("RatingValid", transfer.RATINGVALID_NO), zap.Any("err", err))

			buyNOCnt = 0 //出错设置为0
		}
		rNO.Buy = buyNOCnt                     //买入数量
		rNO.Stdrating = transfer.STDRATING_BUY //买入

		//增持数量
		enlargeNOCnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_ENLARGE, transfer.RATINGVALID_NO)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_ENLARGE), zap.String("RatingValid", transfer.RATINGVALID_NO), zap.Any("err", err))

			enlargeNOCnt = 0 //出错设置为0
		}
		rNO.Enlarge = enlargeNOCnt                                       //增持数量
		rNO.Stdrating = rNO.Stdrating + "," + transfer.STDRATING_ENLARGE //增持

		//中性数量
		neutralNOCnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_NEUTRAL, transfer.RATINGVALID_NO)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_NEUTRAL), zap.String("RatingValid", transfer.RATINGVALID_NO), zap.Any("err", err))

			neutral18Cnt = 0 //出错设置为0
		}
		rNO.Neutral = neutralNOCnt                                       //中性数量
		rNO.Stdrating = rNO.Stdrating + "," + transfer.STDRATING_NEUTRAL // 中性

		//减持数量
		reduceNOCnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_REDUCE, transfer.RATINGVALID_NO)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_REDUCE), zap.String("RatingValid", transfer.RATINGVALID_NO), zap.Any("err", err))

			reduceNOCnt = 0 //出错设置为0
		}
		rNO.Reduce = reduceNOCnt                                        //减持数量
		rNO.Stdrating = rNO.Stdrating + "," + transfer.STDRATING_REDUCE //减持

		//卖出数量
		sellNOCnt, err := mdb.GetStdRatingCounts(ctx, symbol, transfer.STDRATING_SELL, transfer.RATINGVALID_NO)
		if err != nil {
			global.LOG.Error("获取相关标准评级和评级有效期的机构个数出错:", zap.String("StdRating", transfer.STDRATING_SELL), zap.String("RatingValid", transfer.RATINGVALID_NO), zap.Any("err", err))

			sellNOCnt = 0 //出错设置为0
		}
		rNO.Sell = sellNOCnt                                          //卖出数量
		rNO.Stdrating = rNO.Stdrating + "," + transfer.STDRATING_SELL //卖出

		// 增加评级有效期12个月的记录
		rows = append(rows, rNO)
	}

	return rows, nil
}

//GetTqExptSkinvRatingBySymbol 投资评级 根据symbol取得证券所有评级信息
func (mdb *db) GetTqExptSkinvRatingBySymbol(ctx context.Context, symbol string) ([]*domain.TQ_EXPT_SKINVRATING, error) {
	var results []*domain.TQ_EXPT_SKINVRATING
	err := mdb.db.NewSession().Where("ISVALID = ? and SYMBOL = ?", 1, symbol).Find(&results)
	return results, err
}

//GetAllRating 取得所有机构评级信息
func (mdb *db) GetAllRating(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.RATING, error) {
	var rows []*domain.RATING

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		skinvratings, err := mdb.GetTqExptSkinvRatingBySymbol(ctx, symbol)
		if err != nil {
			global.LOG.Error("获取投资评级数据出错:", zap.Any("err", err))
			return nil, err
		}

		for _, s := range skinvratings {

			if s.Stdrating != "" {
				r := new(domain.RATING)

				r.Symbol = symbol                               //证券编码
				r.Compcode = compCode                           //机构代码
				r.Exchange = transfer.TransferExchane(exchange) //市场代码
				r.Rating = s.Stdrating                          //最新评级-->标准评级
				r.Compname = s.Compname                         //评级机构名称 研究机构
				r.Lastrating = s.Stdrating                      //上次评级-->标准评级
				r.Radjustdir = s.Radjustdir                     //评级调整方向
				r.Reportdate = s.Reportdate                     // 研报日期
				r.Skcode = s.Skcode                             //个股预测内码
				r.Analystname = s.Analystname                   //研究员
				r.Ratingvalid = s.Ratingvalid                   //评级有效期

				rows = append(rows, r)
			}

		}
	}

	return rows, nil
}

//GetTqSkShareStruChgByCompCode 根据compCode获取股本结构变化
func (mdb *db) GetTqSkShareStruChgByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_SHARESTRUCHG, error) {
	var results []*domain.TQ_SK_SHARESTRUCHG
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetAllEquityStructure 获取所有股本结构信息
func (mdb *db) GetAllEquityStructure(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.EQUITY_STRUCTURE, error) {
	var rows []*domain.EQUITY_STRUCTURE

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		shareStruChgs, err := mdb.GetTqSkShareStruChgByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取股本结构数据出错:", zap.Any("err", err))
			return nil, err
		}

		for _, s := range shareStruChgs {
			r := new(domain.EQUITY_STRUCTURE)

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构代码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Totalshare = s.Totalshare                     //总股本
			r.Circskamt = s.Circskamt                       //已流通股份合计
			r.Circskrto = s.Circskrto                       //已上市流通股占比
			r.Circskamtnolim = s.Circskamt                  //无限售流通股份
			r.Circskrtonolim = s.Circskrto                  //无限售流通股份占比
			r.Circhamt = s.Circhamt                         //境外上市流通股
			r.Hsharerto = s.Hsharerto                       //境外上市流通股占比
			r.Ncircamt = s.Ncircamt                         //未流通股份合计
			r.Nonnegskrto = s.Nonnegskrto                   //未流通股份合计占比
			r.Circaamt = s.Circaamt                         //已上市流通A股
			r.Asharerto = s.Asharerto                       //已上市流通A股占比
			r.Circbamt = s.Circbamt                         //已上市流通B股
			r.Bsharerto = s.Bsharerto                       //已上市流通B股占比
			r.Ncircamt1 = s.Ncircamt                        //未流通股份
			r.Nonnegskrto1 = s.Nonnegskrto                  //未流通股份占比
			r.Begindate = s.Begindate                       //变动起始日
			r.Exrightdate = s.Exrightdate                   //除权除息日
			r.Publishdate = s.Publishdate                   //信息发布日期

			rows = append(rows, r)
		}

	}
	return rows, nil
}

//GetAllEquityStruChg 获取所有股本变动信息
func (mdb *db) GetAllEquityStruChg(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.EQUITY_STRUCTURE_CHANGE, error) {
	var rows []*domain.EQUITY_STRUCTURE_CHANGE

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		shareStruChgs, err := mdb.GetTqSkShareStruChgByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取股本结构数据出错:", zap.Any("err", err))

			return nil, err
		}

		for _, s := range shareStruChgs {
			r := new(domain.EQUITY_STRUCTURE_CHANGE)

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构代码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Begindate = s.Begindate                       //变动开始日期
			r.Shchgrsn = s.Shchgrsn                         //股份变动原因
			r.Totalshare = s.Totalshare                     //总股本
			r.Totalsharechg = s.Totalsharechg               //总股本变动数量
			r.Skchgexp = s.Skchgexp                         //变动日期股本说明 变动方向
			r.Exrightdate = s.Exrightdate                   //除权除息日

			rows = append(rows, r)
		}
	}
	return rows, nil
}

//GetTqSkOtsHolderByCompCode 根据compCode获取流通股东名单
func (mdb *db) GetTqSkOtsHolderByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_OTSHOLDER, error) {
	var results []*domain.TQ_SK_OTSHOLDER
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetAllTenCirculatingSharesHolder 获取所有十大流通股股东
func (mdb *db) GetAllTenCirculatingSharesHolder(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.TEN_CIRCULATING_SHARES_HOLDER, error) {
	var rows []*domain.TEN_CIRCULATING_SHARES_HOLDER

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		otsHolders, err := mdb.GetTqSkOtsHolderByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取流通股东名单出错:", zap.Any("err", err))
			return nil, err
		}

		for _, o := range otsHolders {
			r := new(domain.TEN_CIRCULATING_SHARES_HOLDER)

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构编码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Shholdername = o.Shholdername                 //股东名称
			r.Holderrto = o.Holderrto                       //占比
			r.Pctofflotshares = o.Pctofflotshares           //占流通股比例
			r.Holdersumchg = o.Holdersumchg                 //增减
			r.Holdersumchgrate = o.Holdersumchgrate         //增减幅度
			r.Shholdercode = o.Shholdercode                 //股东代码
			r.Holderamt = o.Holderamt                       //持股数
			//r.Publishdate = o.Publishdate                 //信息发布日期
			r.Publishdate = o.Enddate //信息发布日期
			r.Enddate = o.Enddate     //截止日期
			r.Rank = o.Rank           //股东排名

			rows = append(rows, r)
		}

	}
	return rows, nil
}

//GetAllBonusFinancing 取得所有分红融资
func (mdb *db) GetAllBonusFinancing(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.BONUS_FINANCING, error) {
	var rows []*domain.BONUS_FINANCING

	for _, v := range basicInfos {
		compCode := v.Compcode
		symbol := v.Symbol
		exchange := v.Exchange

		bonus, err := mdb.GetTqSkBonusByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取股票分红出错:", zap.Any("err", err))

			return nil, err
		}

		for _, b := range bonus {
			r := new(domain.BONUS_FINANCING)

			r.Symbol = symbol                               //证券编码
			r.Compcode = compCode                           //机构编码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Recorddate = b.Recorddate                     //权益登记日
			r.Exrightdate = b.Exrightdate                   //除息日
			r.Divibegdate = b.Divibegdate                   //红利发放日
			r.Taxcdividend = b.Taxcdividend                 //税后红利
			r.Bonusimpdate = b.Bonusimpdate                 //公布日期
			r.Capstkbasdate = b.Capstkbasdate               //红利结转份日
			r.Diviimpmarkd = b.Diviimpmarkd                 //进展说明
			r.Bonusyear = b.Bonusyear                       // 分红实施年度
			r.Dividtype = b.Dividtype                       //权益日期类型
			r.Divitype = b.Divitype                         //权益类型

			rows = append(rows, r)
		}
	}
	return rows, nil
}

//GetTqQtBizUnitTrdInfoBySymbol 根据symbol获取营业部的交易公开信息
func (mdb *db) GetTqQtBizUnitTrdInfoBySymbol(ctx context.Context, symbol string) ([]*domain.TQ_QT_BIZUNITTRDINFO, error) {
	var results []*domain.TQ_QT_BIZUNITTRDINFO
	err := mdb.db.NewSession().Where("ISVALID = ? and SYMBOL = ?", 1, symbol).Find(&results)
	return results, err
}

//GetAllRankList 获取所有龙虎榜信息
func (mdb *db) GetAllRankList(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.RANK_LIST, error) {
	var rows []*domain.RANK_LIST

	for _, v := range basicInfos {
		compCode := v.Compcode //机构编码
		symbol := v.Symbol     //证券代码
		exchange := v.Exchange

		bizUnitTrdInfos, err := mdb.GetTqQtBizUnitTrdInfoBySymbol(ctx, symbol)
		if err != nil {
			global.LOG.Error("获取营业部的交易公开信息出错:", zap.Any("err", err))
			return nil, err
		}

		for _, b := range bizUnitTrdInfos {
			r := new(domain.RANK_LIST)

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构编码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Tradedate = b.Tradedate                       //交易日期
			r.Bizsunitname = b.Bizsunitname                 //营业部名称
			r.Amount = b.Amount                             //成交金额
			r.Buyamt = b.Buyamt                             //买入金额
			r.Saleamt = b.Saleamt                           //卖出金额
			r.Chgtype = b.Chgtype                           // 备注
			r.Bizsunitcode = b.Bizsunitcode                 //营业部代码
			r.Transdir = b.Transdir                         //买卖方向

			rows = append(rows, r)

		}
	}

	return rows, nil
}

//GetTqQtBlockTradeBySymbol 根据symbol获取大宗交易
func (mdb *db) GetTqQtBlockTradeBySymbol(ctx context.Context, symbol string) ([]*domain.TQ_QT_BLOCKTRADE, error) {
	var results []*domain.TQ_QT_BLOCKTRADE
	err := mdb.db.NewSession().Where("ISVALID = ? and SYMBOL = ?", 1, symbol).Find(&results)
	return results, err
}

//GetAllBlockTrading 取得所有大宗交易
func (mdb *db) GetAllBlockTrading(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.BLOCK_TRADING, error) {
	var rows []*domain.BLOCK_TRADING

	for _, v := range basicInfos {
		compCode := v.Compcode //机构编码
		symbol := v.Symbol     //证券代码
		exchange := v.Exchange

		blockTrades, err := mdb.GetTqQtBlockTradeBySymbol(ctx, symbol)
		if err != nil {
			global.LOG.Error("获取大宗交易出错:", zap.Any("err", err))
			return nil, err
		}

		for _, b := range blockTrades {
			r := new(domain.BLOCK_TRADING)

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构编码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Tradedate = b.Tradedate                       //交易日期
			r.Tradeprice = b.Tradeprice                     //成交价格
			r.Volume = b.Volume                             //成交数量
			r.Amount = b.Amount                             //成交金额
			r.Buyername = b.Buyername                       //买方名称
			r.Sellername = b.Sellername                     //卖方名称
			r.Rate = b.Rate                                 //折溢价
			r.Blocktradeid = b.Blocktradeid                 //大宗交易ID

			rows = append(rows, r)
		}
	}
	return rows, nil
}

//GetTqCompPersonRecordByPersonalCode 根据personalCode获取个人档案信息
func (mdb *db) GetTqCompPersonRecordByPersonalCode(ctx context.Context, personalCode string) (*domain.TQ_COMP_PERSONRECORD, error) {
	var results []*domain.TQ_COMP_PERSONRECORD
	err := mdb.db.NewSession().Where("ISVALID = ? and PERSONALCODE = ?", 1, personalCode).Desc("ID").Find(&results)
	if err != nil {
		return nil, err
	}
	if len(results) > 0 {
		return results[0], nil
	}
	return nil, err
}

//GetTqCompManagerByCompCode 根据CompCode 获取公司高管信息
func (mdb *db) GetTqCompManagerByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_COMP_MANAGER, error) {
	var results []*domain.TQ_COMP_MANAGER
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetALlCompanyExecutives 取得所有公司高管信息
func (mdb *db) GetALlCompanyExecutives(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.COMPANY_EXECUTIVES, error) {
	var rows []*domain.COMPANY_EXECUTIVES

	for _, v := range basicInfos {
		compCode := v.Compcode //机构编码
		symbol := v.Symbol     //证券代码
		exchange := v.Exchange

		compManagers, err := mdb.GetTqCompManagerByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取公司高管信息出错:", zap.Any("err", err))

			return nil, err
		}

		for _, m := range compManagers {
			r := new(domain.COMPANY_EXECUTIVES)

			personalCode := m.Personalcode //人员代码

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构编码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Cname = m.Cname                               //姓名
			r.Actdutyname = m.Actdutyname                   //职务
			r.Begindate = m.Begindate                       //任职日期
			r.Personalcode = m.Personalcode                 //人物代码
			r.Postype = m.Postype                           //职位属性
			r.Nowstatus = m.Nowstatus                       //当前状态

			personRecord, _ := mdb.GetTqCompPersonRecordByPersonalCode(ctx, personalCode)
			if personRecord != nil {
				r.Gender = personRecord.Gender //性别
				if len(personRecord.Birthday) >= 4 {
					r.Birthday = personRecord.Birthday[:4] //年龄
				}

				r.Degree = personRecord.Degree //学历
				r.Memo = personRecord.Memo     //简介
			}

			rows = append(rows, r)

		}
	}
	return rows, nil
}

//GetTqSkBusiInfoByCompCode 根据compCode 获取公司经营情况数据
func (mdb *db) GetTqSkBusiInfoByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_BUSIINFO, error) {
	var results []*domain.TQ_SK_BUSIINFO
	err := mdb.db.NewSession().Where("COMPCODE = ? and ISVALID = ?  ", compCode, 1).Find(&results)
	return results, err
}

// getRecentReportDateFinPrgIncStatementNew 取得相应会计年度下，最大报告期的数据（1 一季报、2 中报（累计）、3 三季报（累计）、4 年报(累计)）
func getRecentReportDateFinPrgIncStatementNew(record []*domain.TQ_FIN_PRGINCSTATEMENTNEW, reportYear string) *domain.TQ_FIN_PRGINCSTATEMENTNEW {

	var subRecord []*domain.TQ_FIN_PRGINCSTATEMENTNEW

	for _, r := range record {
		if r.Reportyear == reportYear {
			subRecord = append(subRecord, r)
		}
	}

	//同一会计年度下，最大报告期的记录
	if len(subRecord) > 0 {
		maxRecord := subRecord[0]
		for _, r := range subRecord { //合并期末的数据
			if strings.Compare(maxRecord.Reportdatetype, r.Reportdatetype) == -1 {
				maxRecord = r
			}
		}
		return maxRecord
	}

	return nil
}

//GetAllMainComposition 取得公司所有主要业务信息
func (mdb *db) GetAllMainComposition(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.MAIN_COMPOSITION, error) {
	var rows []*domain.MAIN_COMPOSITION
	var err error
	cache := make(map[string]string)

	for _, v := range basicInfos {
		compCode := v.Compcode //机构编码
		symbol := v.Symbol     //证券代码
		exchange := v.Exchange

		//根据compCode 查询 TQ_SK_BUSIINFO 公司经营状况数据
		busiInfos, err0 := mdb.GetTqSkBusiInfoByCompCode(ctx, compCode)
		if err0 != nil {
			err = err0
		}
		//根据compCode 查询 TQ_FIN_PRGINCSTATEMENTNEW表：一般企业利润表(新准则产品表)
		statementNews, err1 := mdb.GetTqFinPrgIncStatementNewByCompCode(ctx, compCode)
		if err1 != nil {
			err = err1
		}

		// if len(statementNews) > 0 {
		//s := getRecentReportDateFinPrgIncStatementNew(statementNews)
		for _, s := range statementNews { //可能存在reportType=1 但是 reportDateType为1，2，3，4的四条数据
			r := new(domain.MAIN_COMPOSITION)

			r.Compcode = compCode                           //机构编码
			r.Symbol = symbol                               //证券编码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码

			reportYear := s.Reportyear //会计年度 例如：2021
			cacheKey := reportYear + compCode

			has, _ := cache[cacheKey]
			if has != "1" {
				s = getRecentReportDateFinPrgIncStatementNew(statementNews, reportYear)

				if s != nil {
					bizTotCost := s.Biztotcost //营业总成本
					perProfit := s.Perprofit   //营业利润

					r.Biztotcost = bizTotCost
					r.Perprofit = perProfit
					r.Reportyear = reportYear
				}

				infoArray := getSkBizInfo(reportYear, busiInfos, r) //行业分类信息
				if infoArray != nil {
					productInfo, err2 := json.Marshal(infoArray)
					if err2 != nil {
						err = err2
					}
					r.Productinfo = string(productInfo) //产品业务信息

					if len(r.Productinfo) > 0 {
						rows = append(rows, r)
						cache[cacheKey] = "1" //已经计算过了
					}
				}
			}

		}

	}

	return rows, err
}

// getRecentTqSKBizInfo 取得公司最新报表日期的公司经营状况信息
func getRecentTqSKBizInfo(infos []*domain.TQ_SK_BUSIINFO, reportYear string) []*domain.TQ_SK_BUSIINFO {

	var subInfos []*domain.TQ_SK_BUSIINFO
	for _, s := range infos {
		if s.Publishdate[0:4] == reportYear && transfer.TYPE_STYLE_PRODUCT == s.Typestyle { //同一个会计年度 只统计分类口径为：产品的
			subInfos = append(subInfos, s)
		}
	}

	//取得同一年度的最大的PublishDate的数据
	maxPublishDate := ""
	if len(subInfos) > 0 {
		info := subInfos[0]
		for _, o := range subInfos {
			if strings.Compare(o.Publishdate, info.Publishdate) == 1 {
				info = o
			}
		}
		maxPublishDate = info.Publishdate
	}

	//查询出最新PublishDate的数据
	var results []*domain.TQ_SK_BUSIINFO
	for _, info := range subInfos {
		if info.Publishdate == maxPublishDate {
			results = append(results, info)
		}
	}

	return results
}

// getSkBizInfo 取得企业的行业分类信息
func getSkBizInfo(reportYear string, infos []*domain.TQ_SK_BUSIINFO, m *domain.MAIN_COMPOSITION) []*domain.BUSI_CLASS_INFO {

	var rows []*domain.BUSI_CLASS_INFO

	//for _, v := range infos {
	//	if v.Compcode == compCode { //同一个机构编码
	//		publishDate := v.Publishdate        //报表日期 20201231
	//		if publishDate[0:4] == reportYear { //同一个会计年度，可能存在多个PublishDate的数据，取最新的数据
	//			if transfer.TYPE_STYLE_PRODUCT == v.Typestyle { //只统计分类口径为：产品的

	results := getRecentTqSKBizInfo(infos, reportYear) //年度最新数据

	for _, v := range results {
		m.Publishdate = v.Publishdate //报表日期
		m.Typestyle = v.Typestyle     //分类口径

		r := new(domain.BUSI_CLASS_INFO)

		r.CLASSNAME = v.Classname           //分类值
		r.TCOREBIZINCOME = v.Tcorebizincome //本期主营业务收入
		r.COREBIZINCRTO = v.Corebizincrto   //占主营业务收入比例

		rows = append(rows, r)
	}

	//			}
	//
	//		}
	//	}
	//}
	return rows
}

//GetTqCompInfoByCompCode 根据compCode获取机构资料信息
func (mdb *db) GetTqCompInfoByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_COMP_INFO, error) {
	var results []*domain.TQ_COMP_INFO
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetAllCompanyProfile 取得公司所有基本情况
func (mdb *db) GetAllCompanyProfile(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.COMPANY_PROFILE, error) {
	var rows []*domain.COMPANY_PROFILE

	for _, v := range basicInfos {
		compCode := v.Compcode //机构编码
		symbol := v.Symbol     //证券代码
		exchange := v.Exchange
		listDate := v.Listdate //上市日期

		compInfos, err := mdb.GetTqCompInfoByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取公司基本情况出错:", zap.Any("err", err))

			return nil, err
		}

		for _, c := range compInfos {
			r := new(domain.COMPANY_PROFILE)

			r.Compcode = compCode                           //机构代码
			r.Symbol = symbol                               //证券代码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Listdate = listDate                           //上市日期
			r.Compname = c.Compname                         //公司名称
			r.Regname = c.Region                            //所属地域
			r.Comptype = c.Comptype1                        //当前行业
			r.Legrep = c.Legrep                             //法人代表
			r.Regcapital = c.Regcapital                     //注册资金
			r.Regaddr = c.Regaddr                           //注册地址
			r.Majorbiz = c.Majorbiz                         //主要业务
			r.Bizscope = c.Bizscope                         //经营范围

			rows = append(rows, r)

		}

	}

	return rows, nil
}

//GetTqSkShareHolderNumByCompCode 根据compCode获取股东户数统计信息
func (mdb *db) GetTqSkShareHolderNumByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_SHAREHOLDERNUM, error) {
	var results []*domain.TQ_SK_SHAREHOLDERNUM
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetSkDailyPricesBySeCodeAndTradeDate 根据Secode和tradeDate获取股票历史日交易信息
func (mdb *db) GetSkDailyPricesBySeCodeAndTradeDate(ctx context.Context, seCode string, tradeDate string) ([]*domain.TQ_QT_SKDAILYPRICE, error) {
	var results []*domain.TQ_QT_SKDAILYPRICE
	err := mdb.db.NewSession().Where("ISVALID=? and TRADEDATE = ? and SECODE = ?", 1, tradeDate, seCode).Desc("ID").Find(&results)
	return results, err
}

//GetAllHolderChange 取得素有股东变动数据
func (mdb *db) GetAllHolderChange(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.HOLDER_CHANGE, error) {
	var rows []*domain.HOLDER_CHANGE

	for _, v := range basicInfos {
		compCode := v.Compcode // 机构代码
		symbol := v.Symbol     //证券代码
		seCode := v.Secode     //证券内码
		exchange := v.Exchange

		//根据compCode取得股东户数统计信息
		skSharesHolders, err := mdb.GetTqSkShareHolderNumByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取股东变动数据出错:", zap.Any("err", err))
			return nil, err
		}

		for _, s := range skSharesHolders {
			r := new(domain.HOLDER_CHANGE)

			r.Symbol = symbol                               //证券代码
			r.Compcode = compCode                           //机构代码
			r.Exchange = transfer.TransferExchane(exchange) //市场代码

			totalShAmt := s.Totalshamt //股东总户数
			totalShRto := s.Totalshrto // 股东总户数交上期增减

			r.Totalshamt = totalShAmt // 股东人数

			if totalShAmt != "0" && totalShAmt != "0.0" && totalShAmt != "null" && totalShAmt != "" {
				// 较上期变化： TOTALSHRTO/TOTALSHAMT
				totalShRtoDec, _ := decimal.NewFromString(totalShRto)
				totalShAmtDec, _ := decimal.NewFromString(totalShAmt)
				chgrtoDec := totalShRtoDec.Div(totalShAmtDec)
				totalShchgrto := chgrtoDec.String()

				r.Totalshchgrto = totalShchgrto //较上期变化
			}

			kavgsh := s.Kavgsh
			r.Kavgsh = kavgsh //户均持股数

			endDate := s.Enddate //截止日期
			r.Enddate = endDate

			//根据endDate和seCode查询TQ_QT_SKDAILYPRICE股票历史交易日信息
			skdailyPrices, err1 := mdb.GetSkDailyPricesBySeCodeAndTradeDate(ctx, seCode, endDate)
			if err1 != nil {
				global.LOG.Error("获取股票历史交易日信息出错:", zap.Any("err", err))

				//return nil, err
			}

			if skdailyPrices != nil && len(skdailyPrices) > 0 {
				sdp := skdailyPrices[0]

				tclose := sdp.Tclose
				r.Tclose = tclose //收盘价

				//人均持股金额(元):公式：TCLOSE收盘价*KAVGSH户均持股数
				tcloseDec, _ := decimal.NewFromString(tclose)
				kavgshDec, _ := decimal.NewFromString(kavgsh)
				kavgholdamtDec := tcloseDec.Mul(kavgshDec)

				kavgholdamt := kavgholdamtDec.String()

				r.Kavgholdamt = kavgholdamt //人均持股金额(元)

			}

			rows = append(rows, r)

		}
	}

	return rows, nil
}

//GetTqSkShareStruChgByCompCodeAndPublishDate 根据compCode和publishDate 获取股本结构变化
func (mdb *db) GetTqSkShareStruChgByCompCodeAndPublishDate(ctx context.Context, compCode string, publishDate string) (*domain.TQ_SK_SHARESTRUCHG, error) {
	var results []*domain.TQ_SK_SHARESTRUCHG
	err := mdb.db.NewSession().Where("ISVALID=?  and COMPCODE = ? and PUBLISHDATE = ?", 1, compCode, publishDate).Desc("ID").Find(&results)
	if err != nil {
		return nil, err
	}
	if len(results) > 0 {
		return results[0], nil
	}
	return nil, nil
}

//GetTqSKShareHolderByCompCode 根据compCode 获取股东名单
func (mdb *db) GetTqSKShareHolderByCompCode(ctx context.Context, compCode string) ([]*domain.TQ_SK_SHAREHOLDER, error) {
	var results []*domain.TQ_SK_SHAREHOLDER
	err := mdb.db.NewSession().Where("ISVALID = ? and COMPCODE = ?", 1, compCode).Find(&results)
	return results, err
}

//GetAllTenHolder 获取十大股东信息
func (mdb *db) GetAllTenHolder(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.TEN_HOLDER, error) {
	var rows []*domain.TEN_HOLDER

	for _, v := range basicInfos {
		symbol := v.Symbol
		compCode := v.Compcode
		exchange := v.Exchange

		tenHolders, err := mdb.GetTqSKShareHolderByCompCode(ctx, compCode)
		if err != nil {
			global.LOG.Error("获取股东名单出错:", zap.Any("err", err))

			return nil, err
		}

		for _, t := range tenHolders {
			r := new(domain.TEN_HOLDER)

			r.Symbol = symbol
			r.Compcode = compCode
			r.Exchange = transfer.TransferExchane(exchange) //市场代码
			r.Shholdername = t.Shholdername                 //股东名称
			r.Holderamt = t.Holderamt                       //持股数
			r.Holderrto = t.Holderrto                       //占比
			r.Curchg = t.Curchg                             //增减
			r.Shholdercode = t.Shholdercode                 //股东代码
			//r.Publishdate = t.Publishdate                   //信息发布日期
			r.Publishdate = t.Enddate //信息发布日期
			r.Enddate = t.Enddate     //截止日期
			r.Rank = t.Rank           //股东排名
			curChgDec, _ := decimal.NewFromString(t.Curchg)
			holderAmtDec, _ := decimal.NewFromString(t.Holderamt)
			sumDec := holderAmtDec.Add(curChgDec)
			if sumDec.String != nil && sumDec.String() != "0" && sumDec.String() != "0.00" && sumDec.String() != "" {
				curChgRageDec := curChgDec.Div(sumDec) //本期变动数量增减幅度:	CURCHG本期变动数量/( HOLDERAMT持股数量 + CURCHG本期变动数量)*100%
				currChgRate := curChgRageDec.String()
				r.Curchgrate = currChgRate //增减幅度
			}

			////取得股本结构变化
			//shareStruChg, err1 := mdb.GetTqSkShareStruChgByCompCodeAndPublishDate(ctx, compCode, t.Publishdate)
			//if err1 != nil {
			//	log.Printf(" 根据公司内码：%v和信息发布日期:%v,获取股本结构信息出错:%v", compCode, t.Publishdate, err.Error())
			//}

			//	if shareStruChg != nil {
			//占流通股比：HOLDERAMT/CIRCAMT
			circAmt := t.Circamt //流通股
			if circAmt != "0.00" && circAmt != "null" && circAmt != "" && circAmt != "0" {
				circAmtDec, _ := decimal.NewFromString(circAmt)
				rtoDec := holderAmtDec.Div(circAmtDec)

				r.Holdcircskamtrto = rtoDec.String() //占流通股比
			}

			//	}

			rows = append(rows, r)

		}
	}
	return rows, nil
}

//GetTqSkFundamentalsBySymbol 根据 symbol获取股票基本面简表
func (mdb *db) GetTqSkFundamentalsBySymbol(ctx context.Context, symbol string) ([]*domain.TQ_SK_FUNDAMENTALS, error) {
	var results []*domain.TQ_SK_FUNDAMENTALS
	err := mdb.db.NewSession().Where("ISVALID = ? and RIGHT(SECODE,6)  = ?", 1, symbol).Find(&results)
	return results, err
}

//GetAllLatestIndicator 获取最新指标
func (mdb *db) GetAllLatestIndicator(ctx context.Context, basicInfos []*domain.TQ_SK_BASICINFO) ([]*domain.LATEST_INDICATOR, error) {
	var rows []*domain.LATEST_INDICATOR

	for _, v := range basicInfos {
		symbol := v.Symbol
		compCode := v.Compcode //公司内码
		exchange := v.Exchange

		var rowsTmp []*domain.LATEST_INDICATOR //每一个compCode对应一个结果集

		//取得股票基本面简信息
		fundamentals, err := mdb.GetTqSkFundamentalsBySymbol(ctx, symbol)
		if err != nil {
			global.LOG.Error("获取股票基本面简信息失败:", zap.Any("err", err))

			return nil, err
		}

		for _, f := range fundamentals { //设置该证券的最新指标信息

			basicEps := f.Basiceps     //每股收益
			naps := f.Naps             //每股净资产
			totalShare := f.Totalshare //总股本
			roe := f.Roe               //净资产收益率
			operCfps := f.Opercfps     //每股经营现金流
			npgrt := f.Npgrt           //净利润同比增长

			//获取主要财务指标信息
			mainIndexs, err1 := mdb.GetTqFinPrgFinMainIndexByCompCode(ctx, compCode)
			if err1 != nil {
				global.LOG.Error("获取主要财务指标(产品表）信息失败:", zap.Any("err", err1))

				return nil, err1
			}

			for _, m := range mainIndexs {
				r := new(domain.LATEST_INDICATOR)

				r.Compcode = compCode
				r.Symbol = symbol
				r.Exchange = transfer.TransferExchane(exchange) //市场代码

				r.Basiceps = basicEps //每股收益
				r.Naps = naps         //每股净资产

				r.Totalshare = totalShare //总股本
				r.Roe = roe               //净资产收益率
				r.Opercfps = operCfps     //每股经营现金流
				r.Npgrt = npgrt           //净利润同比增长

				reportYear := m.Reportyear
				reportDateType := m.Reportdatetype

				r.Reportdatetype = reportDateType //报告期类型
				r.Reportyear = reportYear         //会计年度

				r.Epsbasicepscut = m.Epsbasicepscut //扣除非经常性损益后的基本每股收益

				r.Enddate = m.Enddate //业务主键

				rowsTmp = append(rowsTmp, r)
			}

			//获取 一般企业利润表信息
			stmns, err2 := mdb.GetTqFinPrgIncStatementNewByCompCode(ctx, compCode)
			if err2 != nil {
				global.LOG.Error("获取一般企业利润表信息失败:", zap.Any("err", err2))

				return nil, err2
			}

			//设置企业利润信息
			rowsTmp = setIncStatement(rowsTmp, stmns)

			//衍生财务指标
			indicDatas, err3 := mdb.GetTqFinPrgIndicDataByCompCode(ctx, compCode)
			if err3 != nil {
				global.LOG.Error("获取衍生财务指标信息失败:", zap.Any("err", err3))

				return nil, err3
			}

			//设置衍生财务指标信息
			rowsTmp = setIndicData4LatestIndicator(rowsTmp, indicDatas)

			// 衍生财务指标副表
			indicDataSub, err4 := mdb.GetTqFinPrgIndicDataSubByCompCode(ctx, compCode)
			if err4 != nil {
				global.LOG.Error("获取衍生财务指标副表失败:", zap.Any("err", err4))
				return nil, err4
			}

			// 设置衍生财务指标副表信息
			rowsTmp = setIndicDataSub4LatestIndicator(rowsTmp, indicDataSub)

			rows = append(rows, rowsTmp...)
		}
	}

	return rows, nil
}

func setIndicDataSub4LatestIndicator(s []*domain.LATEST_INDICATOR, t []*domain.TQ_FIN_PRGINDICDATASUB) []*domain.LATEST_INDICATOR {
	if len(s) == 0 || len(t) == 0 {
		return s
	}
	//if len(s) == len(t) {
	for _, o := range t {
		for _, v := range s {
			if v.Compcode == o.Compcode && v.Enddate == o.Enddate && v.Reportyear == o.Reportyear && v.Reportdatetype == o.Reportdatetype {
				v.Operinyoyb = o.Operinyoyb         ///营收同比增
				v.Netinpnrplyoyb = o.Netinpnrplyoyb //归属母公司股东净利润_扣除非经常性损益_同比（%）
			}
		}

	}
	//} else {
	//	global.LOG.Info("......数据有异常，TQ_FIN_PRGINDICDATASUB 表数量未匹配......", zap.Int("LastIndicatorNum", len(s)), zap.Int("TqFinPrgIndicDataSubNum", len(t)))
	//
	//}
	return s
}

func setIndicData4LatestIndicator(s []*domain.LATEST_INDICATOR, t []*domain.TQ_FIN_PRGINDICDATA) []*domain.LATEST_INDICATOR {
	if len(s) == 0 || len(t) == 0 {
		return s
	}

	//if len(s) == len(t) {
	for _, o := range t {
		for _, v := range s {
			if v.Compcode == v.Compcode && v.Enddate == o.Enddate && v.Reportyear == o.Reportyear && v.Reportdatetype == o.Reportdatetype {
				v.Sgpmargin = o.Sgpmargin //销售毛利率
				v.Npcut = o.Npcut         //扣除非经常性损益后的净利润
			}
		}

	}

	//} else {
	//	global.LOG.Info("......数据有异常，TQ_FIN_PRGINDICDATA 表数量未匹配......", zap.Int("LastIndicatorNum", len(s)), zap.Int("TqFinPrgIndicDataNum", len(t)))
	//
	//}

	return s
}
func setIncStatement(s []*domain.LATEST_INDICATOR, t []*domain.TQ_FIN_PRGINCSTATEMENTNEW) []*domain.LATEST_INDICATOR {
	if len(s) == 0 || len(t) == 0 {
		return s
	}

	//	if len(s) == len(t) {
	for _, o := range t {
		for _, v := range s {
			if v.Compcode == o.Compcode && v.Enddate == o.Enddate && v.Reportyear == o.Reportyear && v.Reportdatetype == o.Reportdatetype {
				v.Bizinco = o.Bizinco     //营业总收入
				v.Netprofit = o.Netprofit //净利润

			}
		}

	}

	//} else {
	//	global.LOG.Info("......数据有异常，TQ_FIN_PRGINCSTATEMENTNEW 表数量未匹配......", zap.Int("LastIndicatorNum", len(s)), zap.Int("TqFinPrgIncStatementNewNum", len(t)))
	//}

	return s
}
